package com.ficus.road.maintain.service;

import com.ficus.road.maintain.core.model.Car;
import com.ficus.road.maintain.core.model.GpsHistory;
import com.ficus.road.maintain.core.model.RecordGps;
import com.ficus.road.maintain.core.model.RecordGpsRequest;
import com.ficus.road.maintain.dao.CarDao;
import com.ficus.road.maintain.dao.GpsHistoryDao;
import com.ficus.road.maintain.dao.GpsHistoryMinuteDao;
import com.ficus.road.maintain.util.MyDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author jinbiao.he
 * @Since 2021/4/8 上午10:19
 */
@Service
@Slf4j
public class GpsHistoryService {
    public static volatile DateFormat sdf = new SimpleDateFormat("yyyyMMdd");

    @Autowired
    private GpsHistoryDao gpsHistoryDao;

    @Autowired
    private CarDao carDao;

    @Autowired
    private GpsHistoryMinuteDao gpsHistoryMinuteDao;

    public String create(GpsHistory gpsHistory) {
        gpsHistoryDao.saveOrUpdate(gpsHistory);
        return gpsHistory.getCarId();
    }

    public String createMinute(GpsHistory gpsHistory) {
        gpsHistoryMinuteDao.saveOrUpdate(gpsHistory);
        return gpsHistory.getCarId();
    }

    public GpsHistory findGpsByCarIdAndTimeStamp(String carId, Long timestamp) {
        Criteria criteria = Criteria.where("car_id").is(carId).and("timestamp").is(timestamp);
        Query query = new Query(criteria);
        return gpsHistoryMinuteDao.findOne(query);
    }

    public List<GpsHistory> findGpsByCarIdAndTimeStampGte(String carId, Long timestamp) {
        Criteria criteria = Criteria.where("car_id").is(carId).and("timestamp").gte(timestamp);
        Query query = new Query(criteria);
        query.with(new Sort(Sort.Direction.ASC, "timestamp"));
        return gpsHistoryDao.findByQuery(query);
    }

    public List<RecordGps> queryRecordGps(RecordGpsRequest recordGpsRequest) {
        Criteria criteria = Criteria.where("timestamp").gt(recordGpsRequest.getStartTime());
        if (recordGpsRequest.getEndTime() != null) {
            criteria.lt(recordGpsRequest.getEndTime());
        }
        List<String> plates = recordGpsRequest.getPlates();
        Map<String, String> plateCarIdMap = carDao.findAll().stream().collect(Collectors.toMap(Car::getPlateNo, Car::getId));
        Map<String, String> carIdPlateMap = carDao.findAll().stream().collect(Collectors.toMap(Car::getId, Car::getPlateNo));
        if (CollectionUtils.isNotEmpty(plates)) {
            List<String> carIds = plates.stream().map(item -> plateCarIdMap.get(item)).collect(Collectors.toList());
            criteria.and("car_id").in(carIds);
        }
        Query query = new Query(criteria);
        query.with(new Sort(Sort.Direction.ASC, "timestamp"));
        List<GpsHistory> gpsHistoryList = gpsHistoryDao.findByQuery(query);
        List<RecordGps> recordGpsList = gpsHistoryList.stream().map(item -> {
            RecordGps recordGps = new RecordGps();
            recordGps.setCarId(item.getCarId());
            recordGps.setLatitude(item.getLatitude());
            recordGps.setLongitude(item.getLongitude());
            recordGps.setAltitude(item.getAltitude());
            recordGps.setTimestamp(item.getTimestamp());
            recordGps.setSpeed(item.getSpeed());
            recordGps.setDirection(item.getDirection());
            recordGps.setPlate(carIdPlateMap.get(item.getCarId()));
            if (ObjectUtils.isNotEmpty(item.getCreationTime())) {
                recordGps.setCreationTime(MyDateUtil.dateFormatStr(item.getCreationTime(), "yyyy-MM-dd'T'HH:mm:ss"));
            }
            return recordGps;
        }).collect(Collectors.toList());
        return recordGpsList;
    }

    //gpsHistoryDao和gpsHistoryMinuteDao分别查询两张不同的表
    public List<GpsHistory> query(Query query) {
        query.with(new Sort(Sort.Direction.ASC, "timestamp"));
        List<GpsHistory> histories = gpsHistoryDao.findByQuery(query);
        return histories;
    }

    //获取车辆的最新的历史记录
    public GpsHistory getLatestHistory(String carId) {
        String format = sdf.format(new Date());
        Date formatDate = null;
        try {
            formatDate = sdf.parse(format);
        } catch (ParseException e) {
            log.error("parse Date met exception:", e);
        }
        Criteria criteria = Criteria.where("car_id").is(carId).and("timestamp").lt(formatDate.getTime() / 1000);
        Query query = new Query(criteria);
        query.with(new Sort(Sort.Direction.DESC, "timestamp"));
        return gpsHistoryDao.findOne(query);
    }

    //获取车辆的开始轨迹
    public GpsHistory getStartHistory(String carId, Date startDate) {
        String format = sdf.format(startDate);
        Date formatDate = null;
        try {
            formatDate = sdf.parse(format);
        } catch (ParseException e) {
            log.error("parse Date met exception:", e);
        }
        Criteria criteria = Criteria.where("car_id").is(carId).and("timestamp").gte(formatDate.getTime() / 1000);
        Query query = new Query(criteria);
        query.with(new Sort(Sort.Direction.ASC, "timestamp"));
        return gpsHistoryDao.findOne(query);
    }

    //获取车辆的最新的历史记录
    public GpsHistory getLatestHistory(String carId, Date startTime) {
        Criteria criteria = Criteria.where("car_id").is(carId).and("timestamp").gte(DateUtils.addDays(new Date(), -1));
        Query query = new Query(criteria);
        query.with(new Sort(Sort.Direction.DESC, "timestamp"));
        return gpsHistoryDao.findOne(query);
    }

    public List<GpsHistory> queryMinute(Query query) {
        query.with(new Sort(Sort.Direction.ASC, "timestamp"));
        List<GpsHistory> histories = gpsHistoryMinuteDao.findByQuery(query);
        return histories;
    }

    // 重置历史轨迹
    public void resetGpsHistory() {
        gpsHistoryDao.deleteAll();

    }

    //删除不合法的gps数据
//    public List<String> deleteGpsData() {
//        new Query(Criteria.where())
//    }

    // 删除指定gps轨迹
    public void deleteGpsHistory(List<String> idList) {
        idList.forEach(id -> {
            gpsHistoryDao.deleteById(id);
        });
    }

    public void createGpsList(List<GpsHistory> list) {
        list.parallelStream().forEach(gpsHistory -> {
            gpsHistoryDao.saveOrUpdate(gpsHistory);
        });
    }
}
